package com.yunhaikeji.core.poi;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import static org.apache.poi.ss.usermodel.Cell.CELL_TYPE_STRING;

/**
 * Project : YunduEduCloud
 * Author  : Bean
 * Contact : guhaibin1847@gmail.com
 */
public class ExcelImportor {

    private Excel excel;

    private ExcelImportor(Excel excel) {
        this.excel = excel;
    }

    public static ExcelImportor from(Excel excel) {
        return new ExcelImportor(excel);
    }

    public static ExcelImportor from(InputStream in) {
        return new ExcelImportor(Excel.readExcel(in));
    }

    public ImportResult doImport(ImportRule rule) {
        return doImport(rule, ConsoleProgress.I);
    }

    public ImportResult doImport(ImportRule rule, ImportProgress progress) {
        if (excel == null || rule == null) {
            return new ImportResult(0);
        }

        Sheet sheet = excel.getSheet(0);
        int rowCount = sheet.getLastRowNum();

        ImportResult result = new ImportResult(rowCount);

        if (progress != null) {
            progress.init(rowCount - 1);
        }

        for (int i = 1; i < rowCount; i++) {
            Row row = sheet.getRow(i);
            int columnCount = row.getLastCellNum();
            List<Object> rowContent = new ArrayList<>();

            for (int j = 0; j < columnCount; j++) {
                Cell cell = row.getCell(j);
                cell.setCellType(CELL_TYPE_STRING);
                String v = cell.getStringCellValue();
                rowContent.add(v);
            }

            ImportResult r = rule.importRow(rowContent);

            if (progress != null) {
                progress.update(i);
            }
            result.merge(r);
        }
        if (progress != null) {
            progress.end(result);
        }
        return result;
    }

    public interface ImportRule {
        ImportResult importRow(List<Object> row);
    }

    public interface ImportProgress {
        void init(int all);

        void update(int current);

        void end(ImportResult result);
    }

    public static class ConsoleProgress implements ImportProgress {

        public static final ConsoleProgress I = new ConsoleProgress();

        private int all;

        private ConsoleProgress() {
        }

        @Override
        public void init(int all) {
            this.all = all;
        }

        @Override
        public void update(int current) {
            float percent = (current / (float) all) * 100;
        }

        @Override
        public void end(ImportResult result) {
            System.out.println(result);
        }


    }

    public static void main(String[] args) {
        ImportProgress progress = new ConsoleProgress();
        progress.init(100);
        for (int i = 10; i < 101; i = i + 10) {
            progress.update(i);
        }
    }

    public static class ImportResult {
        private int rowCount;
        private int allRow;
        private int successRow;
        private int failedRow;
        private List<String> infos;

        public ImportResult(int rowCount) {
            this.rowCount = rowCount;
            this.allRow = 0;
            this.successRow = 0;
            this.failedRow = 0;
        }

        public void merge(ImportResult result) {
            this.successRow += result.successRow;
            this.failedRow += result.failedRow;
            this.allRow = this.successRow + this.failedRow;
            if (result.infos != null) {
                if (infos == null) {
                    infos = new ArrayList<>(result.infos);
                } else {
                    infos.addAll(result.infos);
                }
            }
        }

        public int getAllRow() {
            return allRow;
        }

        public void setAllRow(int allRow) {
            this.allRow = allRow;
        }

        public int getSuccessRow() {
            return successRow;
        }

        public void setSuccessRow(int successRow) {
            this.successRow = successRow;
        }

        public int getFailedRow() {
            return failedRow;
        }

        public void setFailedRow(int failedRow) {
            this.failedRow = failedRow;
        }

        public List<String> getInfos() {
            return infos;
        }

        public void setInfos(List<String> infos) {
            this.infos = infos;
        }
    }
}
